namespace Magecrawl.Utilities {
    // This code was taken from bresenham_c.c from libtcod
    // This code is except from many of the normal coding conversions
    // as it is a port of C code
    public class BresenhamLine {
        private readonly int deltax;

        private readonly int deltay;

        private readonly int destx;

        private readonly int desty;

        private readonly int stepx;

        private readonly int stepy;

        private int e;

        private int origx;

        private int origy;

        public BresenhamLine( Point from, Point to ) {
            this.origx = from.X;
            this.origy = from.Y;
            this.destx = to.X;
            this.desty = to.Y;
            this.deltax = to.X - from.X;
            this.deltay = to.Y - from.Y;

            this.stepx = this.deltax > 0 ? 1 : ( this.deltax < 0 ? -1 : 0 );
            this.stepy = this.deltay > 0 ? 1 : ( this.deltay < 0 ? -1 : 0 );

            var xbyx = this.stepx * this.deltax;
            var ybyy = this.stepy * this.deltay;

            if ( xbyx > ybyy ) {
                this.e = xbyx;
                this.deltax *= 2;
                this.deltay *= 2;
            }
            else {
                this.e = ybyy;
                this.deltax *= 2;
                this.deltay *= 2;
            }
        }

        public Point Step() {
            var xbyx = this.stepx * this.deltax;
            var ybyy = this.stepy * this.deltay;

            if ( xbyx > ybyy ) {
                if ( this.origx == this.destx ) {
                    return Point.Invalid;
                }
                this.origx += this.stepx;
                this.e -= ybyy;
                if ( this.e < 0 ) {
                    this.origy += this.stepy;
                    this.e += xbyx;
                }
            }
            else {
                if ( this.origy == this.desty ) {
                    return Point.Invalid;
                }
                this.origy += this.stepy;
                this.e -= xbyx;
                if ( this.e < 0 ) {
                    this.origx += this.stepx;
                    this.e += ybyy;
                }
            }
            return new Point( this.origx, this.origy );
        }
    }
}
